﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;

namespace MyJsonSerialization
{
    class JsonSerializer
    {
        internal JsonObject Serialize(object obj)
        {
            if (obj == null)
            {
                throw new ArgumentNullException();
            }

            JsonObject result = new JsonObject(SerializeObject(obj));

            return result;
        }

        /// <summary>
        /// Serialize an object
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private string SerializeObject(object obj)
        {
            PropertyInfo[] properties = obj.GetType().GetProperties();
            StringBuilder str = new StringBuilder("{");

            foreach (var item in properties)
            {
                if (item.PropertyType.IsGenericType)
                {
                    str.Append(SerializeGeneric(item, item.GetValue(obj, null)));
                }
                else if (item.PropertyType.IsValueType)
                {
                    str.Append(SerializeValue(item, item.GetValue(obj, null)));
                }
                else
                {
                    str.Append(SerializeObject(item));
                }
            }

            str.Remove(str.Length - 1, 1);
            str.Append("}");

            return str.ToString();
        }

        /// <summary>
        /// Serialize an object of value type
        /// </summary>
        /// <param name="item"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        private string SerializeValue(PropertyInfo prop, object obj)
        {
            StringBuilder str = new StringBuilder(String.Format("{0}: ", prop.Name));
            str.Append(String.Format("\"{0}\",", obj.ToString()));

            return str.ToString();
        }

        /// <summary>
        /// Serialize an object of generic type
        /// </summary>
        /// <param name="item"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        private string SerializeGeneric(PropertyInfo prop, object obj)
        {
            StringBuilder str = new StringBuilder("[");
            str.Append(String.Format("{0}: ", prop.Name));

            foreach (var item in (IList)obj)
            {
                if (!item.GetType().IsGenericType)
                {
                    str.Append(String.Format("\"{0}\",", obj.ToString()));
                }
                else
                {
                    throw new NotSupportedException();
                }
            }

            str.Remove(str.Length - 1, 1);
            str.Append("]");

            return str.ToString();
        }
    }
}
